/**
 * Software License, Version 1.0
 * 
 * Copyright 2003 The Trustees of Indiana University.  All rights reserved.
 * 
 *
 *Redistribution and use in source and binary forms, with or without 
 *modification, are permitted provided that the following conditions are met:
 *
 *1) All redistributions of source code must retain the above copyright notice,
 * the list of authors in the original source code, this list of conditions and
 * the disclaimer listed in this license;
 *2) All redistributions in binary form must reproduce the above copyright 
 * notice, this list of conditions and the disclaimer listed in this license in
 * the documentation and/or other materials provided with the distribution;
 *3) Any documentation included with all redistributions must include the 
 * following acknowledgement:
 *
 *"This product includes software developed by the Community Grids Lab. For 
 * further information contact the Community Grids Lab at 
 * http://communitygrids.iu.edu/."
 *
 * Alternatively, this acknowledgement may appear in the software itself, and 
 * wherever such third-party acknowledgments normally appear.
 * 
 *4) The name Indiana University or Community Grids Lab or NaradaBrokering, 
 * shall not be used to endorse or promote products derived from this software 
 * without prior written permission from Indiana University.  For written 
 * permission, please contact the Advanced Research and Technology Institute 
 * ("ARTI") at 351 West 10th Street, Indianapolis, Indiana 46202.
 *5) Products derived from this software may not be called NaradaBrokering, 
 * nor may Indiana University or Community Grids Lab or NaradaBrokering appear
 * in their name, without prior written permission of ARTI.
 * 
 *
 * Indiana University provides no reassurances that the source code provided 
 * does not infringe the patent or any other intellectual property rights of 
 * any other entity.  Indiana University disclaims any liability to any 
 * recipient for claims brought by any other entity based on infringement of 
 * intellectual property rights or otherwise.  
 *
 *LICENSEE UNDERSTANDS THAT SOFTWARE IS PROVIDED "AS IS" FOR WHICH NO 
 *WARRANTIES AS TO CAPABILITIES OR ACCURACY ARE MADE. INDIANA UNIVERSITY GIVES
 *NO WARRANTIES AND MAKES NO REPRESENTATION THAT SOFTWARE IS FREE OF 
 *INFRINGEMENT OF THIRD PARTY PATENT, COPYRIGHT, OR OTHER PROPRIETARY RIGHTS. 
 *INDIANA UNIVERSITY MAKES NO WARRANTIES THAT SOFTWARE IS FREE FROM "BUGS", 
 *"VIRUSES", "TROJAN HORSES", "TRAP DOORS", "WORMS", OR OTHER HARMFUL CODE.  
 *LICENSEE ASSUMES THE ENTIRE RISK AS TO THE PERFORMANCE OF SOFTWARE AND/OR 
 *ASSOCIATED MATERIALS, AND TO THE PERFORMANCE AND VALIDITY OF INFORMATION 
 *GENERATED USING SOFTWARE.
 */
package cgl.narada.wsinfra.wsa.impl;

import org.apache.xmlbeans.XmlCursor;

import cgl.narada.wsinfra.exception.ProcessingException;
import cgl.narada.wsinfra.schemas.addressing.AttributedURI;
import cgl.narada.wsinfra.schemas.addressing.EndpointReferenceType;
import cgl.narada.wsinfra.schemas.addressing.ReferenceParametersType;
import cgl.narada.wsinfra.schemas.addressing.ReferencePropertiesType;
import cgl.narada.wsinfra.schemas.addressing.ToDocument;
import cgl.narada.wsinfra.schemas.soap.BodyType;
import cgl.narada.wsinfra.schemas.soap.EnvelopeDocument;
import cgl.narada.wsinfra.schemas.soap.EnvelopeType;
import cgl.narada.wsinfra.schemas.soap.HeaderType;
import cgl.narada.wsinfra.util.XmlContentTransfer;
import cgl.narada.wsinfra.wsa.AddressingHeaders;
import cgl.narada.wsinfra.wsa.WsaEprRules;

/** This is a utility class which enforces rules related to the creation of
    SOAP messages that are targetted to specific Endpoints. WS-Addrressing
    rules require each element of ReferenceProperties and Reference Parameters
    to be included with the Header of the SOAP message.

    @author Shrideep Pallickara
    $Date: 2005/07/29 22:41:30 $
    $Revision: 1.6 $
*/


public class WsaEprRulesImpl implements WsaEprRules {
  private static final WsaEprRules instance = new WsaEprRulesImpl();
  private XmlContentTransfer xmlContentTransfer;
  private String moduleName = "WsaEprRulesImpl: ";

  private WsaEprRulesImpl() {
    xmlContentTransfer = XmlContentTransfer.getInstance();
  }

  public static WsaEprRules getInstance() {
    return instance;
  }

  public EnvelopeDocument prepareSOAPEnvelope(EndpointReferenceType epr) {

    EnvelopeDocument envelopeDocument = EnvelopeDocument.Factory.newInstance();
    EnvelopeType envelope = envelopeDocument.addNewEnvelope();

    /** First prepare the header of the SOAP envelope to contain the
	action Attribute value */
    HeaderType header = envelope.addNewHeader();

    AttributedURI address = epr.getAddress();
    ToDocument toDoc = ToDocument.Factory.newInstance();
    toDoc.setTo(address);

    XmlCursor headerCursor = header.newCursor();
    headerCursor.toNextToken();//advance cursor so that we can start inserting

    XmlCursor toDocCursor = toDoc.newCursor();
    xmlContentTransfer.copyFromSourceToDestination(toDocCursor, headerCursor);
    toDocCursor.dispose();

    /** Process the reference properties */
    ReferencePropertiesType refProps = epr.getReferenceProperties();
    if (refProps != null) {
      xmlContentTransfer.copyFromSourceToDestination(refProps, headerCursor);
    }

    /** Process the reference parameters */
    ReferenceParametersType refParams = epr.getReferenceParameters();
    if (refParams != null) {
      xmlContentTransfer.copyFromSourceToDestination(refParams, headerCursor);
    }

    headerCursor.dispose();

    /** Add a body to this SOAP Envelope */
    BodyType body = envelope.addNewBody();

    return envelopeDocument;
  }

  
  /** Adds the [wsa:To] element to the specified envelope document based on
      the rules specified in WS-Addressing. */
  public void prepareSOAPEnvelope(EnvelopeDocument envelopeDocument,
				  EndpointReferenceType epr) 
    throws ProcessingException {
    String errorReport = null;
    if (envelopeDocument == null) {
      errorReport = moduleName + "The specified Envelope is NULL!";
      throw new ProcessingException(errorReport);
	
    }
    
    if (epr == null) {
      errorReport = moduleName + "Specified EndpointReferenceType is NULL!";
      throw new ProcessingException(errorReport);
    }
    
    EnvelopeType envelope = envelopeDocument.getEnvelope();

    /** First prepare the header of the SOAP envelope to contain the
	action Attribute value */
    HeaderType header;
    
    if (envelope.isSetHeader()) {
      header = envelope.getHeader();
    } else {
      header = envelope.addNewHeader();
    }

    AttributedURI address = epr.getAddress();
    ToDocument toDoc = ToDocument.Factory.newInstance();
    toDoc.setTo(address);

    XmlCursor headerCursor = header.newCursor();
    headerCursor.toNextToken();//advance cursor so that we can start inserting

    XmlCursor toDocCursor = toDoc.newCursor();
    xmlContentTransfer.copyFromSourceToDestination(toDocCursor, headerCursor);
    toDocCursor.dispose();

    /** Process the reference properties */
    ReferencePropertiesType refProps = epr.getReferenceProperties();
    if (refProps != null) {
      xmlContentTransfer.copyFromSourceToDestination(refProps, headerCursor);
    }

    /** Process the reference parameters */
    ReferenceParametersType refParams = epr.getReferenceParameters();
    if (refParams != null) {
      xmlContentTransfer.copyFromSourceToDestination(refParams, headerCursor);
    }

    headerCursor.dispose();
  }



  
  /** This method returns the endpoint reference type to which a message must 
      be issued to, based on the supplied addressingHeaders. This method 
      returns a NULL if either the addressingHeders is NULL or any one of the 
      following elements viz. ReplyTo or From - is not present in the
      supplied  AddressingHeaders */
  public EndpointReferenceType 
  sendTo(AddressingHeaders addressingHeaders) {
    if (addressingHeaders == null) {
      System.out.println(moduleName +
			 "The addressing headers passed here is NULL");
      return null;
    }
    
    
    if (addressingHeaders.hasReplyTo() ) {
      return addressingHeaders.getReplyTo().getReplyTo();
    }
    
    if (addressingHeaders.hasFrom() ) {
      return addressingHeaders.getFrom().getFrom();
    }
    
    System.out.println(moduleName + "No (ReplyTo or From) elements " +
		       "have been specified in the AddressingHeaders");
    return null;
  }
  
}

